package com.eryos.android.cigarettecounter.io;

import java.io.File;
import java.io.IOException;

import android.os.Environment;
import android.util.Log;

/**
 * Project : CigaretteCounter Author : Olivier Combe URL : http://eryos.fr/CigaretteCounter/
 * 
 * Copyright(C)2011 - Olivier Combe
 * 
 * Licensed under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 * 
 * @version \$Revision.*\$
 * @author Olivier Combe
 */
public abstract class IOStream {

    private boolean externalStorageIsAvailable = false;
    private boolean externalStorageIsWriteable = false;

    protected enum TYPE {
        READ, WRITE
    }

    private File path;
    private File outputFile;

    private String externalFilename = "output.csv";

    /**
     * Default Constructor.
     */
    public IOStream() {
        Log.d("CigaretteCounter", getClass().getSimpleName() + " : new IOStream()");
    }

    /**
     * @return Return the complete path of the file.
     */
    public String getFullPathName() {
        return "" + outputFile;
    }

    /**
     * This method check if the external media is available or not(in read or write mode).
     */
    public void checkStorageAvailability() {
        Log.d("CigaretteCounter", getClass().getSimpleName() + " : checkStorageAvailability");

        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            externalStorageIsAvailable = true;
            externalStorageIsWriteable = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            externalStorageIsAvailable = true;
            externalStorageIsWriteable = false;
        } else {
            // Something else is wrong. It may be one of many other states, but all we need
            // to know is we can neither read nor write
            externalStorageIsAvailable = false;
            externalStorageIsWriteable = false;
        }

        Log.d("CigaretteCounter", getClass().getSimpleName() + " : checkStorageAvailability : Available : "
                + externalStorageIsAvailable + " / Writable : " + externalStorageIsWriteable);
    }

    /**
     * Open a stream.
     * 
     * @param typeArg
     *            of stream (read/write)
     * @return true if the stream is correctly opened
     * @throws IOException
     *             in case of error
     */
    public boolean openStream(final TYPE typeArg) throws IOException {
        Log.d("CigaretteCounter", getClass().getSimpleName() + " : openStream " + typeArg);

        try {
            checkStorageAvailability();

            if (typeArg.equals(TYPE.READ) && externalStorageIsAvailable || typeArg.equals(TYPE.WRITE)
                    && externalStorageIsAvailable && externalStorageIsWriteable) {

                /*
                 * if (android.os.Build.VERSION.SDK_INT > 7) { path =
                 * Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); } else {
                 */
                path = Environment.getExternalStorageDirectory();
                path = new File(path.getAbsolutePath() + "/Download");
                /* } */

                outputFile = new File(path, externalFilename);

                if (path.exists() || path.mkdirs()) {
                    if (outputFile.exists() && typeArg.equals(TYPE.WRITE)) {
                        outputFile.delete();
                    }

                    return true;
                } else {
                    Log.w(getClass().getSimpleName(), "openStream : path.mkdirs()fails !");
                    return false;
                }
            } else {
                Log.w(getClass().getSimpleName(), "openStream : SD not available !");
                return false;
            }

        } catch (Exception e) {
            Log.e(getClass().getSimpleName(), "openStream", e);
            return false;
        }
    }

    /**
     * Close current stream.
     * 
     * @throws IOException
     *             in case of error
     */
    public abstract void closeStream() throws IOException;

    /**
     * @return the path
     */
    public final File getPath() {
        return path;
    }

    /**
     * Sets the path.
     * 
     * @param pathArg
     *            the value to set
     */
    public final void setPath(final File pathArg) {
        this.path = pathArg;
    }

    /**
     * @return the outputFile
     */
    public final File getOutputFile() {
        return outputFile;
    }

    /**
     * Sets the outputFile.
     * 
     * @param outputFileArg
     *            the value to set
     */
    public final void setOutputFile(final File outputFileArg) {
        this.outputFile = outputFileArg;
    }

    /**
     * @return the externalFilename
     */
    public final String getExternalFilename() {
        return externalFilename;
    }

    /**
     * Sets the externalFilename.
     * 
     * @param externalFilenameArg
     *            the value to set
     */
    public final void setExternalFilename(final String externalFilenameArg) {
        this.externalFilename = externalFilenameArg;
    }

}
